package main

import (
	"context"
	"fmt"
	"sync"
	"time"
)

type Site interface {
	//方法
	Query(string) string
}

func someQ(s Site, str string) string {
	return s.Query(str)
}

type Baidu struct {
}

func (B Baidu) Query(str string) string {
	fmt.Printf("query  baidu starting \n")
	time.Sleep(1 * time.Second)
	return "baidu " + str
}

type Google struct {
}

func (G Google) Query(str string) string {
	fmt.Printf("query  google starting \n")
	time.Sleep(5 * time.Second)
	return "google " + str
}

func QALL(sites []Site, wg *sync.WaitGroup) chan string {
	resChan := make(chan string, len(sites))
	for _, site := range sites {
		go func(site Site, resChan chan string) {
			wg.Add(1)
			resChan <- site.Query("gogogogo")
			wg.Done()
		}(site, resChan)

	}
	//fmt.Printf("chan %d %+v",len(resChan),resChan)
	return resChan
}

func QSingle(ctx context.Context, sites []Site) {
	ch := make(chan string, len(sites))
	ctx1, cancel := context.WithCancel(ctx)
	ctxTimeout, _ := context.WithTimeout(ctx, 500*time.Microsecond)
	for _, site := range sites {
		go func(ch chan string, site Site, cancel context.CancelFunc) {
			ch <- someQ(site, "single")
			cancel()
		}(ch, site, cancel)
	}

	select {
	case <-ctxTimeout.Done():
		fmt.Printf("timeout \n")
		return
	case <-ctx1.Done():
		fmt.Printf("singel priint %s \n", <-ch)
		return
	}
}

func main() {

	str := "1231dsd9jldfjkfggdZ"

	for k, v := range str {
		if v > 59 {
			fmt.Printf("string %s \n", string(str[k]))
		} else {
			fmt.Printf("int %s \n", string(str[k]))
		}
		fmt.Print("%+v \n", v)
	}

	ctx, cancelP := context.WithCancel(context.Background())

	b := Baidu{}
	g := Google{}
	//b.Query()
	//someQ(b)
	//var wg sync.WaitGroup

	sites := []Site{b, g}
	/*resAll := QALL(sites, &wg)
	wg.Wait()

	for v := range resAll{
		fmt.Printf("resALL %s \n",v)
	}
	close(resAll)
	fmt.Printf("resALL is done \n")
	*/
	QSingle(ctx, sites)
	//子进程代用结束 直接将主ctxcancel掉
	cancelP()

	time.Sleep(1 * time.Second)
	return
}
